package nckd.wnqjt.tmc.tda.plugin.form;

import com.alibaba.fastjson.JSON;
import kd.bos.algo.DataSet;
import kd.bos.algo.FilterFunction;
import kd.bos.algo.JoinType;
import kd.bos.algo.Row;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.LocaleString;
import kd.bos.entity.qing.*;
import kd.bos.form.IPageCache;
import kd.bos.form.plugin.AbstractFormPlugin;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.servicehelper.QueryServiceHelper;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author zhujintao
 * @date 2024/11/05
 * @desc 资金集中度
 */
public class ConcentrationOfFundsQingDataProvider extends AbstractFormPlugin implements IQingDataProvider {
    private static Log log = LogFactory.getLog(ConcentrationOfFundsQingDataProvider.class);

    /**
     * 获取表头信息定义
     */
    @Override
    public QingMeta getMeta(String pageId) {
        String entityKey = "bei_bankbalance";
        QingMeta meta = new QingMeta();
        EntryEntity entity = new EntryEntity();
        entity.setKey(entityKey); //实体名(唯一标识)	是
        entity.setName(new LocaleString("余额查询")); //实体别名	是
        entity.setPkFieldName("id");//主键名称	是
        meta.addEntryEntity(entity);

        Field column = new Field();
        column.setEntity(entityKey);//字段所属实体key	否
        column.setKey("id");// 字段名(唯一标识)	是
        column.setFieldType(QingFieldType.Int.toNumber()); //数据类型	是
        column.setName(new LocaleString("id")); //字段别名	是
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);//字段所属实体key	否
        column.setKey("companyname");// 字段名(唯一标识)	是
        column.setFieldType(QingFieldType.String.toNumber()); //数据类型	是
        column.setName(new LocaleString("申请组织")); //字段别名	是
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("concentrationoffunds");
        column.setFieldType(QingFieldType.Number.toNumber());
        column.setName(new LocaleString("资金集中度"));
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("numerator");
        column.setFieldType(QingFieldType.Number.toNumber());
        column.setName(new LocaleString("分子"));
        meta.addColumn(column);

        column = new Field();
        column.setEntity(entityKey);
        column.setKey("denominator");
        column.setFieldType(QingFieldType.Number.toNumber());
        column.setName(new LocaleString("分母"));
        meta.addColumn(column);

        /*column = new Field();
        column.setEntity(entityKey);
        column.setKey("bizdate");
        column.setFieldType(QingFieldType.DateTime.toNumber());
        column.setName(new LocaleString("日期"));
        meta.addColumn(column);*/
        return meta;
    }

    /**
     * 获取轻分析数据
     *
     * @param startRow 起始行
     * @param limit    每页的数据量
     * @return 轻分析数据
     */
    @Override
    public QingData getData(String pageId, int startRow, int limit) {
        //拿过滤条件，进行取数
        String qFilter = getPageCache().get("qFilter");
        if (qFilter != null) {
            //通过此方法拿到过滤参数
            Map<String, Object> filterParam = (Map) JSON.parseObject(qFilter, Map.class);
        }
        //子公司上存余额/（子公司当前余额+母公司当前余额+虚拟户【受限资金管理】+虚拟户投资理财）
        //先获取母子账户组的母账户组织，账户，子账户组织，账号
        //母子账户组 fca_acctgroup
        String fcaAcctgroupSelectField = "id,company.id companyid,company.number companynumber,company.name companyname,accountbank.id accountbankid,accountbank.bankaccountnumber parentcompanyaccount, " +
                "entrys.bankacct.id bankacctid,entrys.bankacct.bankaccountnumber subsidiarybankaccount,entrys.bankacct.company.id bankacctcompanyid,entrys.bankacct.company.number bankacctcompanynumber,entrys.bankacct.company.name bankacctcompanyname";
        QFilter fcaacctgroupFilter = new QFilter("enable", QCP.equals, "1");
        //有效的母子账户组
        DataSet fcaAcctgroupDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "fca_acctgroup", fcaAcctgroupSelectField, fcaacctgroupFilter.toArray(), null);
        DataSet fcaAcctgroupCopy = fcaAcctgroupDataSet.copy();
        //将母账户组织，母账户，子账户组织，子账户 分别获取
        Set<Long> parentCompanyIdSet = new HashSet<>();
        Set<Long> subsidiaryCompanyIdSet = new HashSet<>();
        Set<String> parentBankAccountNumberSet = new HashSet<>();
        Set<String> subsidiaryBankAccountNumberSet = new HashSet<>();
        while (fcaAcctgroupCopy.hasNext()) {
            Row next = fcaAcctgroupCopy.next();
            parentCompanyIdSet.add(next.getLong("companyid"));
            subsidiaryCompanyIdSet.add(next.getLong("bankacctcompanyid"));
            parentBankAccountNumberSet.add(next.getString("parentcompanyaccount"));
            subsidiaryBankAccountNumberSet.add(next.getString("subsidiarybankaccount"));
        }
        //查询全部的余额查询表 这里就包括了子账户的上存余额，子账户组织下全部账户的当前余额，母账户的当前余额
        QFilter finorgtype = new QFilter("number", QCP.equals, "FI-015");
        DynamicObject queryOne = QueryServiceHelper.queryOne("bd_finorgtype", "id", finorgtype.toArray());
        QFilter beiBankbalanceFilter = null;
        if (queryOne != null) {
            Object pkValue = queryOne.getLong("id");
            beiBankbalanceFilter = new QFilter("bank.finorgtype.id", QCP.not_equals, pkValue);
        }
        log.info("资金集中度余额查询条件 " + beiBankbalanceFilter.toString());
        //QFilter beiBankbalanceFilter = new QFilter("bank.name", QCP.not_like, "工商银行");
        String beiBankbalanceSelectField = "id,company.id companyid,company.number companynumber,company.name companyname" +
                ",accountbank.id accountbankid,accountbank.bankaccountnumber bankaccountnumber,bizdate,nckd_depositbalance,amount";
        DataSet beiBankbalanceDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "bei_bankbalance", beiBankbalanceSelectField, beiBankbalanceFilter.toArray(), null);
        //日志打印
        StringBuffer beiBankbalanceDataSetlog = new StringBuffer();
        DataSet beiBankbalanceDataSetcopy = beiBankbalanceDataSet.copy();
        while (beiBankbalanceDataSetcopy.hasNext()) {
            Row next = beiBankbalanceDataSetcopy.next();
            beiBankbalanceDataSetlog.append(next.getString("bankaccountnumber")).append(" # ");
        }
        log.info("资金集中度余额查询列表 " + beiBankbalanceDataSetlog);
        //取 账号维度的 最大日期的 上存余额
        DataSet beiBankbalanceGroupDataSet = beiBankbalanceDataSet.groupBy(new String[]{"companyid", "bankaccountnumber"})
                .maxP("bizdate", "nckd_depositbalance")
                .maxP("bizdate", "amount")
                .max("bizdate")
                .finish();

        /**
         * **************************************处理分子***********************************
         */
        //日志打印
        StringBuffer beiBankbalanceGroupDataSetlog = new StringBuffer();
        DataSet beiBankbalanceGroupDataSetcopy = beiBankbalanceGroupDataSet.copy();
        while (beiBankbalanceGroupDataSetcopy.hasNext()) {
            Row next = beiBankbalanceGroupDataSetcopy.next();
            beiBankbalanceGroupDataSetlog.append(next.getString("bankaccountnumber")).append(" # ");
        }
        log.info("资金集中度账户余额查询最大日期列表 " + beiBankbalanceGroupDataSetlog);
        //获取子公司上存余额 上存余额得大于0
        DataSet subsidiaryDepositbalancefilter = beiBankbalanceGroupDataSet.copy().filter("nckd_depositbalance > 0").filter(new FilterFunction() {
            @Override
            public boolean test(Row row) {
                String bankaccountnumber = row.getString("bankaccountnumber");
                if (subsidiaryBankAccountNumberSet.contains(bankaccountnumber)) {
                    return true;
                } else {
                    return false;
                }
            }
        });
        //母子账户组通过子账户关联余额查询的账户 再根据母账户组织进行分组 得到集团本部，建材本部的分子 上存余额 这里生产只有两条记录
        DataSet numeratorDepositbalanceDataSet = fcaAcctgroupDataSet.join(subsidiaryDepositbalancefilter, JoinType.INNER).on("subsidiarybankaccount", "bankaccountnumber")
                .select(fcaAcctgroupDataSet.getRowMeta().getFieldNames(), new String[]{"nckd_depositbalance"}).finish().groupBy(new String[]{"companyid", "companynumber", "companyname"}).sum("nckd_depositbalance").finish();

        /**
         * *******************************处理分母********************************
         */
        //获取子公司当前余额 当前余额得大于0
        //先获取符合条件的账户列表 用母子账户组的子账户组织去账户查询该组织下全部的账户，并根据是否虚拟户拆分
        QFilter acctstatusfilter = new QFilter("acctstatus", QCP.not_equals, "closed").and("company", QCP.in, subsidiaryCompanyIdSet);
        String getAcctSelectedFieds = "id,company,openorg,issetbankinterface,bank,bankaccountnumber,isvirtual,name,currencyname,defaultcurrency,opendate,acctstatus,acctstyle,accttype,acctproperty,manager,acctname,finorgtype";
        DataSet acctDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "bd_accountbanks", getAcctSelectedFieds, acctstatusfilter.toArray(), null);
        //根据是否虚拟户进行分组 非虚拟户去关联余额查询 获取子账户当前余额
        DataSet[] isvirtualDataSets = acctDataSet.splitByFilter(new String[]{"isvirtual = true"}, true);
        //非虚拟户账户
        DataSet notisvirtualDataSet = isvirtualDataSets[1];
        List<String> notisvirtualAccountNoList = new ArrayList<>();
        while (notisvirtualDataSet.hasNext()) {
            Row next = notisvirtualDataSet.next();
            String bankaccountnumber = next.getString("bankaccountnumber");
            notisvirtualAccountNoList.add(bankaccountnumber);
        }
        DataSet subsidiaryAmountfilter = beiBankbalanceGroupDataSet.copy().filter("amount > 0").filter(new FilterFunction() {
            @Override
            public boolean test(Row row) {
                String bankaccountnumber = row.getString("bankaccountnumber");
                if (notisvirtualAccountNoList.contains(bankaccountnumber)) {
                    return true;
                } else {
                    return false;
                }
            }
        });
        DataSet denominatorSubsidiaryAmountDataSet = subsidiaryAmountfilter.groupBy().sum("amount").finish();

        //获取母账户当前余额 当前余额得大于0
        DataSet parentAmountfilter = beiBankbalanceGroupDataSet.filter("amount > 0").filter(new FilterFunction() {
            @Override
            public boolean test(Row row) {
                String bankaccountnumber = row.getString("bankaccountnumber");
                if (parentBankAccountNumberSet.contains(bankaccountnumber)) {
                    return true;
                } else {
                    return false;
                }
            }
        });
        DataSet denominatorParentAmountDataSet = parentAmountfilter.groupBy().sum("amount").finish();

        //虚拟户账户
        DataSet isvirtualDataSet = isvirtualDataSets[0];
        List<String> isvirtualAccountNoList = new ArrayList<>();
        while (isvirtualDataSet.hasNext()) {
            Row next = isvirtualDataSet.next();
            String bankaccountnumber = next.getString("bankaccountnumber");
            isvirtualAccountNoList.add(bankaccountnumber);
        }
        //受限资金管理
        String amRestrictedfundsmanagerSelectField = "id,org.id companyid,org.number companynumber,org.name companyname,bankacct.id accountbankid,bankacct.bankaccountnumber bankaccountnumber,unrestrictedamt";
        //增加受限
        QFilter businesstype = new QFilter("businesstype", QCP.equals, "1").and("billstatus", QCP.equals, "C")
                .and("bankacct.bankaccountnumber", QCP.in, isvirtualAccountNoList);
        DataSet amRestrictedfundsmanagerDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "am_restrictedfundsmanager", amRestrictedfundsmanagerSelectField, businesstype.toArray(), null);
        DataSet denominatorSubsidiaryUnrestrictedamtDataSet = amRestrictedfundsmanagerDataSet.groupBy().sum("unrestrictedamt").finish();

        //定期存款处理
        QFilter cimDepositQfilter = new QFilter("billstatus", QCP.equals, "C").and("finaccount", QCP.in, isvirtualAccountNoList);
        String cimDepositSelectField = "id,org.id companyid,org.number companynumber,org.name companyname,settleaccount.id accountbankid,settleaccount.bankaccountnumber bankaccountnumber,surplusamount";
        DataSet cimDepositDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "cim_deposit", cimDepositSelectField, cimDepositQfilter.toArray(), null);
        DataSet denominatorSubsidiarySurplusamountDataSet = cimDepositDataSet.groupBy().sum("surplusamount").finish();

        //资金集中度分母
        List<BigDecimal> denominatorconcentrationoffunds = new ArrayList<>();
        while (denominatorSubsidiaryAmountDataSet.hasNext()) {
            Row next = denominatorSubsidiaryAmountDataSet.next();
            log.info("资金集中度子账户当前余额 " + next.getBigDecimal("amount"));
            denominatorconcentrationoffunds.add(next.getBigDecimal("amount"));
        }
        while (denominatorParentAmountDataSet.hasNext()) {
            Row next = denominatorParentAmountDataSet.next();
            log.info("资金集中度母账户当前余额 " + next.getBigDecimal("amount"));
            denominatorconcentrationoffunds.add(next.getBigDecimal("amount"));
        }
        while (denominatorSubsidiaryUnrestrictedamtDataSet.hasNext()) {
            Row next = denominatorSubsidiaryUnrestrictedamtDataSet.next();
            log.info("资金集中度虚拟户受限资金 " + next.getBigDecimal("unrestrictedamt"));
            denominatorconcentrationoffunds.add(next.getBigDecimal("unrestrictedamt"));
        }
        while (denominatorSubsidiarySurplusamountDataSet.hasNext()) {
            Row next = denominatorSubsidiarySurplusamountDataSet.next();
            log.info("资金集中度虚拟户存款金额 " + next.getBigDecimal("surplusamount"));
            denominatorconcentrationoffunds.add(next.getBigDecimal("surplusamount"));
        }
        //资金总额
        BigDecimal total = denominatorconcentrationoffunds.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        log.info("资金集中度分母资金 " + total);
        numeratorDepositbalanceDataSet = numeratorDepositbalanceDataSet.addField(total.toString(), "denominatoramount");
        numeratorDepositbalanceDataSet = numeratorDepositbalanceDataSet.addField("nckd_depositbalance / denominatoramount * 100", "concentrationoffunds");
        QingData data = null;
        if (startRow < 200) {
            data = new QingData();
            Map<String, Integer> dataindex = new HashMap<String, Integer>();
            dataindex.put("id", 0);
            dataindex.put("companyname", 1);
            dataindex.put("concentrationoffunds", 2);
            dataindex.put("numerator", 3);
            dataindex.put("denominator", 4);

            data.setDataindex(dataindex);

            List<Object[]> rows = new ArrayList<Object[]>();
            while (numeratorDepositbalanceDataSet.hasNext()) {
                Row row = numeratorDepositbalanceDataSet.next();
                Object[] obj = new Object[5];
                obj[0] = row.getLong("companyid");
                obj[1] = row.getString("companyname");
                obj[2] = row.getBigDecimal("concentrationoffunds");
                obj[3] = row.getBigDecimal("nckd_depositbalance");
                obj[4] = row.getBigDecimal("denominatoramount");
                rows.add(obj);
            }
            data.setRows(rows);
        }
        return data;
    }


    @Override
    public void setFilterParameter(String filterParameter) {
        IPageCache pageCache = getPageCache();
        pageCache.put("qFilter", filterParameter);

    }

    @Override
    public String getFilterParameter() {
        return getPageCache().get("qFilter");
    }
}